// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

#include "DBManager/Service/Input/Constraint/ConstraintSummaryService.h"

#include <cassert>
#include <list>
#include <memory>
#include <vector>

#include "DataStructure/Common/Id.h"
#include "DataStructure/Input/Coordinate/CoordTypes.h"
#include "DataStructure/Input/Coordinate/ICoordinate.h"

#include "DBManager/Common/ServiceMacro.h"
#include "DBManager/IRepository/Input/Constraint/IConstraintSummaryRepository.h"

#include "ConstraintSummaryService.h"

using namespace SG::DBManager;

SERVICE_REG_FOR_SUMMARY (ConstraintSummaryService, IConstraintSummaryRepository)

namespace
{
    std::vector<ConstraintSummaryService::SummaryCreateService>* g_summaryCreateCordService = nullptr;
}

ConstraintSummaryService::ConstraintSummaryService (DBServiceFactory* const dbServiceFactory, IConstraintSummaryRepository& repos)
    : InputServiceBase<IRepos> (dbServiceFactory, repos)
{}

ConstraintSummaryService::~ConstraintSummaryService () = default;

std::vector<SG::DataStructure::FEM::ConstraintType> ConstraintSummaryService::GetType (SG::DataStructure::Common::Id id) const
{
    return m_repository.GetType (id);
}

SG::DataStructure::Common::Status ConstraintSummaryService::CopyData (DBServiceFactory* const                    dest,
                                                                      std::vector<SG::DataStructure::Common::Id> ids) const
{
    std::map<std::size_t, std::list<SG::DataStructure::Common::Id>> map;
    for (auto&& id : ids)
    {
        auto types = GetType (id);
        for (auto&& type : types)
        {
            std::size_t typeId = typeid (decltype (type)).hash_code () + type;

            if (map.find (typeId) == map.end ())
            {
                map[typeId] = std::list<SG::DataStructure::Common::Id> ();
            }
            map[typeId].push_back (id);
        }
    }

    auto funMap = m_dbServiceFactory->GetDatabase ()->GetHub()->CopyDataFunMap ();
    for (auto&& pair : map)
    {
        if (funMap.count (pair.first) > 0)
        {
            funMap[pair.first](m_dbServiceFactory, dest, { pair.second.begin (), pair.second.end () });
        }
    }

    return SG::DataStructure::Common::Status::STATUS_Success;
}

bool ConstraintSummaryService::RegisterService (SummaryCreateService&& service)
{
    if (g_summaryCreateCordService == nullptr)
        ::g_summaryCreateCordService = new std::vector<SummaryCreateService> ();

    ::g_summaryCreateCordService->emplace_back (std::move (service));
    return true;
}

void ConstraintSummaryService::CreateSummary (DBServiceFactory* const dbServiceFactory)
{
    for (size_t i = 0; i < g_summaryCreateCordService->size (); i++)
    {
        g_summaryCreateCordService->at (i) (dbServiceFactory);
    }
}
